package com.intelij.adapter;

import com.intelij.adapter.entity.Document;
import com.intelij.adapter.eums.SourceType;
import com.intelij.adapter.eums.TargetType;
import com.intelij.adapter.source.Source;
import com.intelij.adapter.source.adapter.SourceAdapter;
import com.intelij.adapter.target.Target;
import com.intelij.adapter.target.adapter.TargetAdapter;
import com.intelij.adapter.util.ClassUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 转换服务类
 */
public class ConversionService {

    //获取单例对象的方法
    private static final String INSTANCE_METHOD_NAME = "getInstance";
    //适配类的扫描路径
    private static final String SCANNER_PACKAGE_PATH="com.intelij.adapter";
    private static final ConcurrentHashMap<SourceType, Class<SourceAdapter>> sourceAdapters = new ConcurrentHashMap();
    private static final ConcurrentHashMap<TargetType, Class<TargetAdapter>> targetAdapters = new ConcurrentHashMap();

    static {
        //注意此处不能使用线程上下文类加载器，应使用加载com.intelij.adapter包下的类的类加载器，不然会找不到类
        ClassUtil.getClassList(SCANNER_PACKAGE_PATH,()->ConversionService.class.getClassLoader(), cls -> {
            if (cls.isEnum()) {
                String name = cls.getFields()[0].getName();
                if (SourceAdapter.class.isAssignableFrom(cls)) {
                    SourceType sourceType = SourceType.getSourceTypeByName(name);
                    if (sourceType != null)
                        sourceAdapters.put(sourceType, cls);
                } else if (TargetAdapter.class.isAssignableFrom(cls)) {
                    TargetType targetType = TargetType.getTargetTypeByName(name);
                    if (targetType != null)
                        targetAdapters.put(targetType, cls);
                }
            }
            return false;
        });
    }

    public static Target convert(Source source, SourceType sourceType, TargetType targetType) {
        Class<SourceAdapter> sourceAdapterClass = sourceAdapters.get(sourceType);
        SourceAdapter sourceAdapter = invokeGetInstance(sourceAdapterClass);
        Document document=sourceAdapter.adapter(source);
        Class<TargetAdapter> targetAdapterClass = targetAdapters.get(targetType);
        TargetAdapter targetAdapter = invokeGetInstance(targetAdapterClass);
        Target target=targetAdapter.adapter(document);
        return target;
    }

    public static Target convert(Source source, String sourceExtName, String targetExtName) {
        return convert(source, SourceType.getSourceTypeByExt(sourceExtName), TargetType.getTargetTypeByExt(targetExtName));
    }

    public static Target convert(Source source, SourceType sourceType, String targetExtName) {
        return convert(source, sourceType, TargetType.getTargetTypeByExt(targetExtName));
    }

    public static Target convert(Source source, String sourceExtName, TargetType targetType) {
        return convert(source, SourceType.getSourceTypeByExt(sourceExtName), targetType);
    }

    /**
     * 通过反射获取单例对象
     * @param tClass
     * @param <T>
     * @return
     */
    public static<T> T invokeGetInstance(Class<T> tClass){
        T t=null;
        try {
            Method method = tClass.getMethod(INSTANCE_METHOD_NAME);
            t=(T)method.invoke(null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return t;
    }

}
